package server;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yangpeng
 * @time 2020/4/2
 * @since 1.0.0
 */
public class ServletWrapper {
    private Map<String,HttpServlet> servletMap = new HashMap<String,HttpServlet>();
    private Map<String,String> classPathMap = new HashMap<String,String>();
    private String webXmlPath;

    private Map<String,String> staticFile = new HashMap<>();

    private MyClassLoader classLoader;

    private String appParentPath;


    public ClassLoader getClassLoader() {
        return classLoader;
    }

    public void setClassLoader(MyClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public Map<String, HttpServlet> getServletMap() {
        return servletMap;
    }

    public void setServletMap(Map<String, HttpServlet> servletMap) {
        this.servletMap = servletMap;
    }

    public String getWebXmlPath() {
        return webXmlPath;
    }

    public void setWebXmlPath(String webXmlPath) {
        this.webXmlPath = webXmlPath;
    }

    public Map<String, String> getStaticFile() {
        return staticFile;
    }

    public void setStaticFile(Map<String, String> staticFile) {
        this.staticFile = staticFile;
    }

    public void loadStaticFile(File app) {
        this.appParentPath = app.getAbsolutePath().replaceAll(app.getName(),"");
        File[] list = app.listFiles();
        for (File file : list) {
            if(file.isFile()){
                if(file.getAbsolutePath().equalsIgnoreCase(this.webXmlPath)){
                    continue;
                }
                String url = file.getAbsolutePath().replace(appParentPath, "");
                url = url.replaceAll("\\\\","/");
                staticFile.put(url,file.getAbsolutePath());
            }
            if(file.isDirectory()){
                if(file.getName().equalsIgnoreCase("server")){
                    continue;
                }
                loadChildList(file);
            }
        }
    }

    private void loadChildList(File file) {
        File[] files = file.listFiles();
        for (File f : files) {
            if(f.isFile()){
                String url = file.getAbsolutePath().replaceAll(appParentPath, "");
                staticFile.put(url,file.getAbsolutePath());
                continue;
            }
            if(file.isDirectory()){
                loadChildList(file);
            }
        }
    }

    public void loadServlet(File file) throws FileNotFoundException {
        loadClassMapping(file);
        //读取web.xml
        InputStream resourceAsStream = new FileInputStream(this.webXmlPath);
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();

            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element =  selectNodes.get(i);
                // <servlet-name>lagou</servlet-name>
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletnameElement.getStringValue();
                // <servlet-class>server.LagouServlet</servlet-class>
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletclassElement.getStringValue();


                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                // /lagou
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                String absolutePath = classPathMap.get(servletClass);

                servletMap.put(urlPattern, (HttpServlet) this.classLoader.findClass(absolutePath).newInstance());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private void loadClassMapping(File file) {
        String absolutePath = file.getAbsolutePath();
        File[] files = file.listFiles();
        for (File classFile : files) {
            if(classFile.isFile() && classFile.getName().endsWith(".class")){
                String url = classFile.getAbsolutePath().replace(absolutePath, "");
                url = url.replaceAll("/", ".");
                url = url.replaceAll("\\\\", ".");
                url = url.replaceAll(".class", "");
                if(url.charAt(0) =='.'){
                    url = url.substring(1);
                }
                this.classPathMap.put(url,classFile.getAbsolutePath());
            }
            if(classFile.isDirectory()){
                loadClassMapping(classFile);
            }
        }
    }
}
